package org.theSeed.singleSecurity.config;

import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.theSeed.base.pojo.constant.SysConstant;
import org.theSeed.rbacBaseCommon.pojo.constant.RbacConstant;
import org.theSeed.singleSecurity.contract.AuthFilterHandler;
import org.theSeed.singleSecurity.handlers.SeedAccessDeniedHandler;
import org.theSeed.singleSecurity.handlers.SeedAuthenticationEntryPoint;

@Slf4j
@EnableWebSecurity
@Configuration
@ConfigurationProperties(prefix = "seed")
@AutoConfigureBefore({SecurityAutoConfiguration.class})
public class SingleSecurityConfig{
    @Getter
    @Setter
    private String[] whiteUrl;

    @Getter
    @Setter
    private String whiteUrlFlagHeaderName = RbacConstant.SEED_WHITE_URL_FLAG;

    @Autowired(required = false)
    private AuthFilterHandler authFilterHandler;

    /**
     * 加密器
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    // 设置全局角色前缀
    @Bean
    public GrantedAuthorityDefaults grantedAuthorityDefaults() {
        return new GrantedAuthorityDefaults(SysConstant.EMPTY_STR); // 无前缀
    }

    /**
     * security自定义配置
     * @return
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return http -> {
            http.ignoring()
                .antMatchers(whiteUrl);
        };
    }

    /**
     * 过滤器链配置
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        if (ObjectUtil.isNotNull(authFilterHandler)){
            http.addFilterBefore(authFilterHandler.getAuthFilter(), UsernamePasswordAuthenticationFilter.class);
        }

        //不需要session
        http
                .csrf(csrf -> csrf.disable())
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .rememberMe(remeberMe->remeberMe.disable());

        //不需要自带的formLogin
        //不需要自带的logout
        http.formLogin(form->form.disable())
                .logout(form->form.disable());

        //异常处理
        http.exceptionHandling()
                .accessDeniedHandler(new SeedAccessDeniedHandler())
                .authenticationEntryPoint(new SeedAuthenticationEntryPoint());
        return http.build();
    }
}
